package org.jeecg.modules.weixin.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.zxing.WriterException;
import javafx.geometry.Point2D;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.jeecg.common.api.vo.Result;

import org.jeecg.common.util.DateUtils;
import org.jeecg.modules.reserve.entity.*;
import org.jeecg.modules.reserve.entity.vo.SdxcReservePlaceVo;
import org.jeecg.modules.reserve.mapper.SdxcReserveEntryMapper;
import org.jeecg.modules.reserve.mapper.SdxcReserveUserMapper;
import org.jeecg.modules.reserve.service.*;
import org.jeecg.modules.reserve.utils.QiniuUpload;
import org.jeecg.modules.reserve.utils.LocationUtil;
import org.jeecg.modules.weixin.constant.WxConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;

import static org.jeecg.modules.reserve.utils.QRCodeGenerator.generateQRCodeImage;
import static org.springframework.http.ResponseEntity.ok;


@Slf4j
@RestController
@RequestMapping("/weixin")
public class WxController {
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    private ISdxcReserveService iSdxcReserveService;
    @Autowired
    private ISdxcReserveUserService iSdxcReserveUserService;
    @Autowired
    private ISdxcReserveEntryService iSdxcReserveEntryService;

    /**
     * 微信小程序用户登录获取用户openid
     *
     * @param
     * @return
     */
    @GetMapping("/login")
    @ApiOperation(value = "用户授权登录", notes = "用户授权登录")
    public Result<?> login(@ApiParam(name = "code", value = "授权code", required = true) @RequestParam("code") String code) {
        String url = WxConstant.LOGIN_URL.replace("APPID", WxConstant.APP_ID).replace("SECRET", WxConstant.APP_SECRET).replace("JSCODE",code);

        log.info("授权登录请求url====={}" , url);
        String resStr = restTemplate.getForObject(url, String.class);
        JSONObject resJson = JSON.parseObject(resStr);
        log.info("授权登录响应========={}", resJson);

        if(null == resJson || resJson.containsKey("errcode")) {
            return Result.error("登录失败");
        }
        //  获取用户openid
        String openid = resJson.getString("openid");
        if(StringUtils.isBlank(openid)) {
            return Result.error("openid获取失败，请重试");
        }
        // 保存用户信息
        String userId = iSdxcReserveUserService.saveByOpenId(openid);
        return Result.ok(userId);
    }

    /**
     * 判断用户信息是否已完善
     *
     * @param
     * @return
     */
    @GetMapping("/queryUserStatus")
    public Result<?> queryUserStatus(@RequestParam("userId") String userId) {
        SdxcReserveUser sdxcReserveUser = iSdxcReserveUserService.getById(userId);
        if (sdxcReserveUser != null && SdxcReserveUser.USER_INFO_FINISH_YES.equals(sdxcReserveUser.getIsFinish())) {
            // 用户信息已完善
            return Result.ok(SdxcReserveUser.USER_INFO_FINISH_YES);
        } else {
            // 用户不存在或信息未完善
            return Result.ok(SdxcReserveUser.USER_INFO_FINISH_NO);
        }
    }

    /**
     * 保存用户信息
     *
     * @param sdxcReserveUser
     * @return
     */
    @PutMapping("/saveUserInfo")
    public Result<?> saveUserInfo(@RequestBody SdxcReserveUser sdxcReserveUser) {
        if(StringUtils.isBlank(sdxcReserveUser.getId())) {
            return Result.error("用户ID为空");
        }
        SdxcReserveUser save = iSdxcReserveUserService.getById(sdxcReserveUser.getId());
        if(null == save) {
            return Result.error("用户信息不存在");
        }
        // 状态为信息已完善
        sdxcReserveUser.setIsFinish(SdxcReserveUser.USER_INFO_FINISH_YES);
        iSdxcReserveUserService.updateById(sdxcReserveUser);
        return Result.ok("保存成功!");
    }

    @Autowired
    private ISdxcReservePlaceService iSdxcReservePlaceService;
    @Autowired
    private ISdxcReservePlaceRecordService iSdxcReservePlaceRecordService;

    /**
     * 获取场地使用明细
     *
     * @return
     */
    @GetMapping("/getPlaceDetail")
    public Result<?> getPlaceDetail() {
        // 查询所有可用场地
        QueryWrapper<SdxcReservePlace> queryWrapper = new QueryWrapper();
        queryWrapper.eq("status", "1");
        List<SdxcReservePlace> palceList = iSdxcReservePlaceService.selectList(queryWrapper);
        // 返回结果
        List<SdxcReservePlaceVo> placeVoList = new ArrayList<>();
        if(null != palceList && palceList.size() > 0) {
            for(SdxcReservePlace place : palceList) {
                String dateBeg = DateUtils.formatDate(new Date(),"yyyyMMdd");
                String dateEnd = DateUtils.formatDate(DateUtils.addDate(new Date(),1),"yyyyMMdd");
                // 查询当天预约记录
                List<SdxcReservePlaceRecord> recordListBeg = iSdxcReservePlaceRecordService.queryRecordDetail(place.getId(), dateBeg);
                placeVoList.add(setReserveVo(recordListBeg,place, new Date()));

                // 查询第二天预约记录
                List<SdxcReservePlaceRecord> recordListEnd = iSdxcReservePlaceRecordService.queryRecordDetail(place.getId(), dateEnd);
                placeVoList.add(setReserveVo(recordListEnd,place, DateUtils.addDate(new Date(),1)));
            }
        }
        return  Result.ok(placeVoList);
    }

    /**
     * 组装前端场地明细数据
     *
     * @param recordList
     * @param place
     * @param date
     * @return
     */
    private SdxcReservePlaceVo setReserveVo(List<SdxcReservePlaceRecord> recordList,SdxcReservePlace place, Date date) {
        SdxcReservePlaceVo placeVo = new SdxcReservePlaceVo();
        placeVo.setPlaceId(place.getId());
        placeVo.setPlaceName(place.getName());
        placeVo.setTotal(Integer.toString(place.getPlaceLimit()));
        if(null != recordList && recordList.size() > 0) {
            placeVo.setIsUse(Integer.toString(recordList.get(0).getIsReserve()));
            placeVo.setRemain(Integer.toString(place.getPlaceLimit() - recordList.get(0).getUsed()));
        } else { // 当天无记录
            placeVo.setIsUse("1");
            placeVo.setRemain(Integer.toString(place.getPlaceLimit()));
        }
        String reserveWeek = DateUtils.dateToWeek(date);
        String reserveDate = DateUtils.formatDate(date,"MM") + "月" + DateUtils.formatDate(date,"dd") + "日";
        placeVo.setReserveWeek(reserveWeek);
        placeVo.setReserveDate(reserveDate+"("+ reserveWeek +")");

        placeVo.setDate(DateUtils.formatDate(date,"yyyy-MM-dd"));
        return placeVo;
    }

    /**
     * 查询用户当日预约记录，判断当日是否可预约，
     * 如果当日该场地已有审核中或审核通过的数据，提示用户不可预约
     *
     * @param userId 用户id
     * @param placeId 场地id
     * @param date 入场时间
     * @return
     */
    @GetMapping("/queryReserve")
    public Result<?> queryReserve(@RequestParam("userId") String userId,
                                  @RequestParam("placeId") String placeId,
                                  @RequestParam("date") String date) {
        QueryWrapper<SdxcReserve> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("place_id", placeId);
        Date now = new Date();
        try {
            now = DateUtils.parseDate(date,"yyyy-MM-dd");
        } catch (ParseException e) {
        }
        queryWrapper.eq("entry_time", now);
        queryWrapper.in("status", 1, 2);
        SdxcReserve sdxcReserve = iSdxcReserveService.getOne(queryWrapper);
        if (null != sdxcReserve) {
            return Result.error("当日该场地已有预约记录，请勿重复预约");
        }
        return Result.ok();
    }

    /**
     * 上传健康码 到七牛云
     *
     * @param request
     * @param response
     * @return
     */
    @PostMapping(value = "/upload")
    public Result<?> upload(HttpServletRequest request, HttpServletResponse response) {
        try {
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            // 获取上传文件对象
            MultipartFile mfile = multipartRequest.getFile("file");
            // 获取图片格式
            String suffix = mfile.getOriginalFilename().substring(mfile.getOriginalFilename().lastIndexOf('.'));
            // 文件名 uuid+图片格式
            String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
            // 上传图片到七牛云 返回访问全路径
            String dbpath = QiniuUpload.updateFile(mfile, fileName);
            return Result.ok(dbpath);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Result.error(e.getMessage());
        }
    }

    /**
     * 保存预约记录
     *
     * @param sdxcReserve
     * @return
     */
    @PutMapping("/saveReserve")
    public Result<?> saveReserve(@RequestBody SdxcReserve sdxcReserve) throws IOException, WriterException {
        String entryDate = sdxcReserve.getEntryDate();
        try {
            sdxcReserve.setEntryTime(DateUtils.parseDate(entryDate,"yyyy-MM-dd"));
        } catch (ParseException e) {
            return Result.error("预约日期有误");
        }
        sdxcReserve.setId(UUID.randomUUID().toString().replace("-",""));
        // 审核中
        sdxcReserve.setStatus(2);
        iSdxcReserveService.save(sdxcReserve);
        SdxcReservePlace sdxcReservePlace = iSdxcReservePlaceService.getById(sdxcReserve.getPlaceId());
        sdxcReservePlace.setPlaceLimit(sdxcReservePlace.getPlaceLimit()-1);
        iSdxcReservePlaceService.updateById(sdxcReservePlace);
        String id=sdxcReserve.getPlaceId();
            String qrCode = id;
            generateQRCodeImage(qrCode,350, 350, "A://IntelliJdaima//two//" + qrCode+".png");
        return Result.ok("保存成功!");
    }
    /**
     * 获取七牛云私有空间下载路径
     *
     * @param baseUrl
     * @return
     */
    @GetMapping("/getDownloadUrl")
    public Result<?> getDownloadUrl(@RequestParam(name = "baseUrl") String baseUrl) {
        String downloadUrl = QiniuUpload.getDownloadUrl(baseUrl);
        if(!StringUtils.isBlank(downloadUrl)) {
            return Result.ok(downloadUrl);
        }
        return Result.error("下载地址获取失败");
    }

    @Autowired
    private SdxcReserveUserMapper sdxcReserveUserMapper;
    /**
     * 查询用户个人信息
     *
     * @param
     * @return
     */
    @GetMapping("/getUserInfo")
    public Result<?> getUserInfo(@RequestParam("userId") String userId) {
      /* List<SdxcReserveUser> list=iSdxcReserveUserService.queryUser(userId);*/
        SdxcReserveUser userInfo = iSdxcReserveUserService.getById(userId);
       return  Result.OK(userInfo);
    }

    /**
     * 查询⽤户预约记录
     *
     * @param userId
     * @return
     */
 /*   @GetMapping("/queryReserveListByUserId")
    public Result<?> queryReserveListByUserId(@RequestParam(name = "userId") String userId) {
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("user_id",userId);
        SdxcReserve sdxcReserve = iSdxcReserveService.getOne(queryWrapper);
        SdxcReservePlace sdxcReservePlace = iSdxcReservePlaceService.getById(sdxcReserve.getPlaceId());
        sdxcReserve.setPlaceName(sdxcReservePlace.getName());
        return Result.OK(sdxcReserve);
    }
*/
    /**
     * 查询⽤户预约记录
     *
     * @param userId
     * @return
     */
    @GetMapping("/queryReserveListByUserId")
    public Result<?> queryReserveListByUserId(@RequestParam(name = "userId") String userId) {
        List<SdxcReserve> sdxcReserveList = iSdxcReserveService.queryReserveListByUserId(userId);
        for (SdxcReserve sdxcReserve : sdxcReserveList) {
            if(sdxcReserve.getStatus() == 1) {
                // 审核通过
                String entryDate = DateUtils.formatDate(sdxcReserve.getEntryTime(), "yyyyMMdd");
                String nowDate = DateUtils.formatDate(new Date(), "yyyyMMdd");
                if(entryDate.equals(nowDate)) {
                    // 预约⽇期是当天，⽤户可以⼊场
                    sdxcReserve.setIsEntry(1);
                }
            }
            sdxcReserve.setStatusString(sdxcReserve.getStatus() == 2 ? "审核中" :
                    (sdxcReserve.getStatus() == 1 ? "审核通过" : "审核不通过"));
        }
        return Result.ok(sdxcReserveList);
    }

    /**
     * 保存⼊场记录
     *
     * @param sdxcReserveEntry
     * @return
     */
    @PutMapping("/saveEntryInfo")
    public Result<?> saveEntryInfo(@RequestBody SdxcReserveEntry
                                           sdxcReserveEntry) {
        sdxcReserveEntry.setId(UUID.randomUUID().toString().replace("-",""));
        sdxcReserveEntry.setEntryTime(new Date());
        String longitude = sdxcReserveEntry.getLongitude();
        String latitude = sdxcReserveEntry.getLatitude();
        // 纬度
        if(!StringUtils.isBlank(longitude) && !StringUtils.isBlank(latitude)) {
            // 判断位置信息是否异常
            Integer isUnusual = getDistance(sdxcReserveEntry);
            sdxcReserveEntry.setIsUnusual(isUnusual);
        } else {
            // 未录⼊位置信息
            sdxcReserveEntry.setIsUnusual(SdxcReserveEntry.IS_UNUSUAL_NULL);
        }
        iSdxcReserveEntryService.save(sdxcReserveEntry);
        return Result.ok("保存成功!");
    }
    /**
     * 判断⼊场位置 是否在场地允许的误差范围内
     *
     * @param sdxcReserveEntry
     * @return
     */
    private Integer getDistance(SdxcReserveEntry sdxcReserveEntry) {
        Integer isUnusual = SdxcReserveEntry.IS_UNUSUAL_SUSS;
        String reserveId = sdxcReserveEntry.getReserveId();
        if(StringUtils.isBlank(reserveId)) {
            return isUnusual;
        }
        SdxcReserve reserve = iSdxcReserveService.getById(reserveId);
        if(null == reserve) {
            return isUnusual;
        }
        String placeId = reserve.getPlaceId();
        SdxcReservePlace place = iSdxcReservePlaceService.getById(placeId);
        if(null == place) {
            return isUnusual;
        }
        if(StringUtils.isBlank(place.getLongitude()) ||
                StringUtils.isBlank(place.getLatitude()) ||
                StringUtils.isBlank(place.getDistance())) {
            return isUnusual;
        }
        Point2D point2D_A = new Point2D(Double.parseDouble(sdxcReserveEntry.getLongitude()),
                Double.parseDouble(sdxcReserveEntry.getLatitude()));
        Point2D point2D_B = new Point2D(Double.parseDouble(place.getLongitude()),
                Double.parseDouble(place.getLatitude()));
        // ⽐较⼊场位置与场地位置之间的距离
        double distance = LocationUtil.getDistance(point2D_A, point2D_B);
        if(distance - Double.parseDouble(place.getDistance()) > 0) {
            return SdxcReserveEntry.IS_UNUSUAL_ERO;
        }
        return isUnusual;
    }




    /**
     * 查询⽤户该场地第⼏次⼊场
     *
     * @param
     * @return
     */
    @GetMapping("/queryEntryCount")
    public Result<?> queryEntryCount(@RequestParam("reserveId") String reserveId) {
        /*Integer count = iSdxcReserveEntryService.getEntryCountByReserveId(reserveId);*/
        Integer count=sdxcReserveEntryMapper.selectCount(new QueryWrapper<SdxcReserveEntry>().eq("reserve_id",reserveId));
        return Result.ok(count);
    }





    @Autowired
    private SdxcReserveEntryMapper sdxcReserveEntryMapper;
    /**
     * 查询⽤户⼊场记录
     *
     * @param reserveId
     * @return
     */
    @RequestMapping("/queryEntryListByReserveId")
    public Result<?> queryEntryListByReserveId(@RequestParam(name = "reserveId") String reserveId) {
        QueryWrapper<SdxcReserveEntry> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("reserve_id",reserveId);
        List<SdxcReserveEntry> sdxcReserveEntries = sdxcReserveEntryMapper.selectList(queryWrapper);
        return Result.ok(sdxcReserveEntries);
    }


    /**
     * 取消预约
     *
     * @param
     * @id
     */
    @GetMapping("/quitReserve")
    public Result<?> quitReserve(@RequestParam("id") String id,@RequestParam("placeId") String placeId) {
        Integer isExist=sdxcReserveEntryMapper.selectCount(new QueryWrapper<SdxcReserveEntry>().eq("reserve_id",id));
        if(isExist!=0){
            return Result.ok("操作失败");
        }
        else {
            iSdxcReserveService.delete(id);
            SdxcReservePlace sdxcReservePlace =iSdxcReservePlaceService.getById(placeId);
            sdxcReservePlace.setPlaceLimit(sdxcReservePlace.getPlaceLimit()+1);
            iSdxcReservePlaceService.updateById(sdxcReservePlace);
            return Result.ok("操作成功");
        }

    }

}
